package org.osgroup.service;

import org.osgroup.dto.EquipmentBooking;
import org.osgroup.dto.EquipmentBookingRequest;
import org.osgroup.project.RollerCoaster;
import org.osgroup.visitor.BaseVisitor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 道具预约服务 - 使用银行家算法管理资源
 */
@Service
public class EquipmentBookingService {
    
    @Autowired
    private RollerCoasterService rollerCoasterService;
    
    // 预约记录存储
    private final Map<String, EquipmentBooking> bookings = new ConcurrentHashMap<>();
    private final Map<String, List<EquipmentBooking>> userBookings = new ConcurrentHashMap<>();
    private final AtomicLong bookingIdCounter = new AtomicLong(1);
    
    // 设备ID到索引的映射
    private final Map<String, Integer> equipmentIdToIndex = new HashMap<String, Integer>() {{
        put("waterGun", 0);
        put("raincoat", 1);
        put("phoneBag", 2);
    }};
    
    // 设备名称映射
    private final Map<String, String> equipmentNames = new HashMap<String, String>() {{
        put("waterGun", "水枪");
        put("raincoat", "雨衣");
        put("phoneBag", "手机防水袋");
    }};
    
    // 设备图标映射
    private final Map<String, String> equipmentIcons = new HashMap<String, String>() {{
        put("waterGun", "🔫");
        put("raincoat", "🧥");
        put("phoneBag", "📱");
    }};
    
    // 设备分类映射
    private final Map<String, String> equipmentCategories = new HashMap<String, String>() {{
        put("waterGun", "水上装备");
        put("raincoat", "防护用品");
        put("phoneBag", "电子设备保护");
    }};
    
    // 设备时租费用(元/小时)
    private final Map<String, Integer> equipmentHourlyRates = new HashMap<String, Integer>() {{
        put("waterGun", 20);
        put("raincoat", 15);
        put("phoneBag", 10);
    }};
    
    // 设备押金(元)
    private final Map<String, Integer> equipmentDeposits = new HashMap<String, Integer>() {{
        put("waterGun", 100);
        put("raincoat", 50);
        put("phoneBag", 50);
    }};
    
    /**
     * 获取可用道具列表
     */
    public Map<String, Object> getAvailableEquipment() {
        System.out.println("🔍 [EquipmentBookingService] 开始获取道具列表");
        
        RollerCoaster project = rollerCoasterService.getRollerCoaster();
        if (project == null) {
            System.err.println("❌ RollerCoaster 项目为 null!");
            return Map.of("equipment", new ArrayList<>());
        }
        
        Map<String, Object> equipmentStatus = project.getEquipmentStatus();
        System.out.println("📦 从 RollerCoaster 获取到的设备状态: " + equipmentStatus);
        
        List<Map<String, Object>> equipmentList = new ArrayList<>();
        
        for (Map.Entry<String, Object> entry : equipmentStatus.entrySet()) {
            String equipmentId = entry.getKey();
            @SuppressWarnings("unchecked")
            Map<String, Object> statusMap = (Map<String, Object>) entry.getValue();
            
            Map<String, Object> equipment = new HashMap<>();
            equipment.put("id", equipmentId);
            equipment.put("name", equipmentNames.getOrDefault(equipmentId, equipmentId));
            equipment.put("description", getEquipmentDescription(equipmentId));
            equipment.put("totalQuantity", statusMap.get("total"));
            equipment.put("availableQuantity", statusMap.get("available"));
            equipment.put("status", statusMap.get("status"));
            
            // 🔥 添加前端需要的额外字段
            equipment.put("icon", equipmentIcons.getOrDefault(equipmentId, "🎯"));
            equipment.put("categoryName", equipmentCategories.getOrDefault(equipmentId, "其他"));
            equipment.put("hourlyRate", equipmentHourlyRates.getOrDefault(equipmentId, 10));
            equipment.put("deposit", equipmentDeposits.getOrDefault(equipmentId, 50));
            
            equipmentList.add(equipment);
        }
        
        System.out.println("✅ 处理后的道具列表大小: " + equipmentList.size());
        System.out.println("✅ 道具列表内容: " + equipmentList);
        
        Map<String, Object> response = new HashMap<>();
        response.put("equipment", equipmentList);
        System.out.println("✅ 最终返回数据: " + response);
        return response;
    }
    
    /**
     * 预约道具 - 使用银行家算法验证安全性
     */
    public Map<String, Object> bookEquipment(EquipmentBookingRequest request) {
        RollerCoaster project = rollerCoasterService.getRollerCoaster();
        
        // 验证设备ID
        if (!equipmentIdToIndex.containsKey(request.getEquipmentId())) {
            return createErrorResponse(400, "无效的设备ID");
        }
        
        // 创建资源请求向量
        int[] resourceRequest = new int[3];
        int equipmentIndex = equipmentIdToIndex.get(request.getEquipmentId());
        resourceRequest[equipmentIndex] = request.getQuantity();
        
        // 创建虚拟游客
        BaseVisitor visitor = new BaseVisitor();
        visitor.setName(request.getUserId() != null ? request.getUserId() : "游客" + bookingIdCounter.get());
        
        // 🔥 使用银行家算法检查资源分配的安全性
        boolean isSafe = project.requestEquipment(visitor, resourceRequest);
        
        if (!isSafe) {
            return createErrorResponse(503, "当前资源不足或分配后系统将处于不安全状态,预约失败");
        }
        
        // 创建预约记录
        String bookingId = generateBookingId();
        EquipmentBooking booking = new EquipmentBooking();
        booking.setId(bookingId);
        booking.setEquipmentId(request.getEquipmentId());
        booking.setEquipmentName(equipmentNames.get(request.getEquipmentId()));
        booking.setBookingDate(request.getBookingDate());
        booking.setStartTime(request.getStartTime());
        booking.setEndTime(request.getEndTime());
        booking.setQuantity(request.getQuantity());
        booking.setStatus("CONFIRMED"); // 银行家算法验证通过后直接确认
        booking.setUserId(visitor.getName());
        booking.setCreateTime(LocalDateTime.now());
        booking.setSpecialRequirements(request.getSpecialRequirements());
        
        // 保存预约记录
        bookings.put(bookingId, booking);
        userBookings.computeIfAbsent(visitor.getName(), k -> new ArrayList<>()).add(booking);
        
        System.out.println("✅ 预约成功: " + visitor.getName() + " 预约 " + 
                         booking.getEquipmentName() + " x" + request.getQuantity());
        
        // 返回成功响应
        Map<String, Object> response = new HashMap<>();
        response.put("code", 200);
        response.put("message", "预约成功");
        response.put("data", booking);
        return response;
    }
    
    /**
     * 获取用户预约记录
     */
    public Map<String, Object> getUserBookings(String userId) {
        List<EquipmentBooking> bookingList = userBookings.getOrDefault(userId, new ArrayList<>());
        
        Map<String, Object> response = new HashMap<>();
        response.put("bookings", bookingList);
        return response;
    }
    
    /**
     * 取消预约 - 释放银行家算法占用的资源
     */
    public Map<String, Object> cancelBooking(String bookingId) {
        EquipmentBooking booking = bookings.get(bookingId);
        
        if (booking == null) {
            return createErrorResponse(404, "预约记录不存在");
        }
        
        if ("CANCELLED".equals(booking.getStatus()) || "COMPLETED".equals(booking.getStatus())) {
            return createErrorResponse(400, "预约已取消或已完成,无法重复操作");
        }
        
        RollerCoaster project = rollerCoasterService.getRollerCoaster();
        
        // 创建资源释放向量
        int[] resourceRelease = new int[3];
        int equipmentIndex = equipmentIdToIndex.get(booking.getEquipmentId());
        resourceRelease[equipmentIndex] = booking.getQuantity();
        
        // 创建虚拟游客
        BaseVisitor visitor = new BaseVisitor();
        visitor.setName(booking.getUserId());
        
        // 🔥 释放银行家算法占用的资源
        project.releaseEquipment(visitor, resourceRelease);
        
        // 更新预约状态
        booking.setStatus("CANCELLED");
        
        System.out.println("✅ 取消预约: " + booking.getUserId() + " 取消 " + 
                         booking.getEquipmentName() + " x" + booking.getQuantity());
        
        Map<String, Object> response = new HashMap<>();
        response.put("code", 200);
        response.put("message", "预约取消成功");
        response.put("data", Map.of(
            "bookingId", bookingId,
            "status", "CANCELLED"
        ));
        return response;
    }
    
    // 辅助方法
    
    private String generateBookingId() {
        LocalDateTime now = LocalDateTime.now();
        String dateStr = String.format("%04d%02d%02d", 
            now.getYear(), now.getMonthValue(), now.getDayOfMonth());
        long counter = bookingIdCounter.getAndIncrement();
        return "BK" + dateStr + String.format("%03d", counter);
    }
    
    private String getEquipmentDescription(String equipmentId) {
        switch (equipmentId) {
            case "waterGun":
                return "水上项目专用水枪,射程远,安全性高";
            case "raincoat":
                return "防水雨衣,有效防止衣服被水打湿";
            case "phoneBag":
                return "手机防水袋,保护您的贵重物品";
            default:
                return "游乐项目专用道具";
        }
    }
    
    private Map<String, Object> createErrorResponse(int code, String message) {
        Map<String, Object> response = new HashMap<>();
        response.put("code", code);
        response.put("message", message);
        return response;
    }
}
